/** * Creates a command subscription object for the given topic. When the authenticated device is given * it is used to either check given tenant and device-id from topic or fill this * fields if not given. * * @param topic The topic to subscribe for commands. * @param authenticatedDevice The authenticated device or {@code null}. * @return The CommandSubscription object or {@code null} if the topic does not match the rules. * @throws NullPointerException if topic is {@code null}. */ public static CommandSubscription fromTopic(final String topic, final Device authenticatedDevice) { try { return new CommandSubscription(topic, authenticatedDevice); } catch (final IllegalArgumentException e) { LOG.debug(e.getMessage()); return null; } }
String tenantId = subscription.getTenant(); String deviceId = subscription.getDeviceId(); if (subscription.isAuthenticated()) { 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: {}]", subscription.getTenant(), subscription.getDeviceId(), endpoint.clientIdentifier()); final Map<String, String> items = new HashMap<>(3); items.put(Fields.EVENT, "command published to device");
final CommandSubscription cmdSub = CommandSubscription.fromTopic(subscription.topicName(), authenticatedDevice); if (cmdSub == null) { span.log(String.format("ignoring unsupported topic filter [%s]", subscription.topicName())); sendDisconnectedTtdEvent(cmdSub.getTenant(), cmdSub.getDeviceId(), authenticatedDevice, null) .setHandler(sendAttempt -> { consumer.close(null); span.log(items); LOG.debug("created subscription [tenant: {}, device: {}, filter: {}, requested QoS: {}, granted QoS: {}]", cmdSub.getTenant(), cmdSub.getDeviceId(), subscription.topicName(), subscription.qualityOfService(), MqttQoS.AT_MOST_ONCE); return cmdSub; TracingHelper.logError(span, items); LOG.debug("cannot create subscription [tenant: {}, device: {}, filter: {}, requested QoS: {}]", cmdSub.getTenant(), cmdSub.getDeviceId(), subscription.topicName(), subscription.qualityOfService(), t); return Future.failedFuture(t); if (f.succeeded() && f.result() instanceof CommandSubscription) { final CommandSubscription s = (CommandSubscription) f.result(); sendConnectedTtdEvent(s.getTenant(), s.getDeviceId(), authenticatedDevice, span.context());
private Future<MessageConsumer> createCommandConsumer(final MqttEndpoint mqttEndpoint, final CommandSubscription sub) { // 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); } 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); }
final CommandSubscription cmdSub = CommandSubscription.fromTopic(topic, authenticatedDevice); if (cmdSub == null) { final Map<String, Object> items = new HashMap<>(2); LOG.debug("ignoring unsubscribe request for unsupported topic filter [{}]", topic); } else { final String tenantId = cmdSub.getTenant(); final String deviceId = cmdSub.getDeviceId(); final Map<String, Object> items = new HashMap<>(2); items.put(Fields.EVENT, "unsubscribing device from topic");