@Test(expected = IllegalStateException.class) public void testMultiSubscribeNeg() throws Exception { Topology top = newTopology("testMultiSubscribeNeg"); int qos = 0; String clientId = newClientId(top.getName()); String topic = getMqttTopics()[0]; // Verify the current behavior of at-most-one subscribe() // for a MqttStreams instance MqttStreams mqtt = new MqttStreams(top, getServerURI(), clientId); mqtt.subscribe(topic, qos); mqtt.subscribe(topic, qos); // should throw }
/** * Publish a {@code TStream<String>} stream's tuples as MQTT messages. * <p> * A convenience function. * The payload of each message is the String tuple's value serialized as UTF-8. * * @param stream Stream to be published. * @param topic the fixed topic. * @param qos the fixed delivery Quality of Service. * @param retain the fixed retain value. * @return TSink sink element representing termination of this stream. */ public TSink<String> publish(TStream<String> stream, String topic, int qos, boolean retain) { return publish(stream, tuple -> topic, tuple -> tuple.getBytes(StandardCharsets.UTF_8), tuple -> qos, tuple -> retain); }
/** * Subscribe to the MQTT topic(s) and create a stream of tuples of type {@code T}. * @param <T> Tuple type * @param topicFilter the topic(s) to subscribe to. * @param qos the maximum Quality of Service to use. * @param message2Tuple function to convert {@code (topic, payload)} to * a tuple of type {@code T} * @return {@code TStream<T>} */ public <T> TStream<T> subscribe(String topicFilter, int qos, BiFunction<String, byte[], T> message2Tuple) { addSubscribe(); return topology().events(new MqttSubscriber<T>(connector, topicFilter, qos, message2Tuple)); }
private String retainTestSetup(boolean isRetained, MsgGenerator mgen) throws Exception { // publish a msg to [not] retain. Topology top = newTopology("retainTestSetup"+isRetained); int qos = 0; String clientId = newClientId(top.getName()); String topic = getMqttTopics()[0]; String retainedMsg = mgen.create(topic, isRetained ? "RETAIN-THIS" : "DO-NOT-RETAIN-THIS"); MqttConfig config = newConfig(getServerURI(), clientId+"-setup"); MqttStreams mqtt = new MqttStreams(top, () -> config); TStream<String> s = PlumbingStreams.blockingOneShotDelay( top.strings(retainedMsg), PUB_DELAY_MSEC, TimeUnit.MILLISECONDS); mqtt.publish(s, topic, qos, isRetained); TStream<String> rcvd = mqtt.subscribe(topic, qos); completeAndValidate(clientId, top, rcvd, mgen, SEC_TIMEOUT, retainedMsg); // N.B. the topology should be shutdown at this point but it isn't // and this topology will also receive and print the tuples // generated by the main portion of the test. // issue#46 return retainedMsg; }
this.connector = new MqttStreams(topology, () -> this.mqttConfig);
private TStream<JsonObject> allCommands() { if (commandStream == null) { String topicFilter = commandTopic(null); commandStream = connector.subscribe(topicFilter, commandQoS, (topic, payload) -> { JsonObject jo = new JsonObject(); jo.addProperty(CMD_DEVICE, deviceId); jo.addProperty(CMD_ID, extractCmd(topic)); jo.addProperty(CMD_TS, System.currentTimeMillis()); String fmt = extractCmdFmt(topic); jo.addProperty(CMD_FORMAT, fmt); if ("json".equals(fmt)) { jo.add(CMD_PAYLOAD, JsonFunctions.fromBytes().apply(payload)); } else { jo.addProperty(CMD_PAYLOAD, new String(payload, StandardCharsets.UTF_8)); } return jo; }) .tag("allDeviceCmds"); } return commandStream; }
@Test public void testAutoClientId() throws Exception { Topology top = newTopology("testAutoClientId"); MsgGenerator mgen = new MsgGenerator(top.getName()); int qos = 0; boolean retain = false; String topic = getMqttTopics()[0]; List<String> msgs = createMsgs(mgen, topic, getMsg1(), getMsg2()); TStream<String> s = PlumbingStreams.blockingOneShotDelay( top.collection(msgs), PUB_DELAY_MSEC, TimeUnit.MILLISECONDS); // Test with auto-generated clientId MqttConfig config = newConfig(getServerURI(), null/*clientId*/); MqttStreams mqtt = new MqttStreams(top, () -> config); mqtt.publish(s, topic, qos, retain); TStream<String> rcvd = mqtt.subscribe(topic, qos); completeAndValidate("some-auto-clientId", top, rcvd, mgen, SEC_TIMEOUT, msgs.toArray(new String[0])); }
MqttStreams mqtt = new MqttStreams(top, () -> config); mqtt.publish(s, tuple -> topic, tuple -> tuple.getBytes(StandardCharsets.UTF_8), TStream<String> rcvd = mqtt.subscribe(topic, qos);
/** * Subscribe to the MQTT topic(s) and create a {@code TStream<String>}. * <p> * A convenience function. * Each message's payload is expected/required to be a UTF-8 encoded string. * Only the converted payload is present the generated tuple. * * @param <T> Tuple type * @param topicFilter the topic(s) to subscribe to. * @param qos the maximum Quality of Service to use. * @return {@code TStream<String>} * @see #publish(TStream, String, int, boolean) */ public <T> TStream<String> subscribe(String topicFilter, int qos) { addSubscribe(); return topology().events(new MqttSubscriber<String>(connector, topicFilter, qos, (topic, payload) -> new String(payload, StandardCharsets.UTF_8))); }
/** * {@inheritDoc} * * <p>The event is published to the configured MQTT {@code mqttDevice.event.topic.pattern}, * as described in the above class documentation, substituting the value returned * by the {@code eventId} function for "{EVENTID}" in the pattern. * The MQTT message's payload is the JSON representation * of the JsonObject stream tuple. */ @Override public TSink<JsonObject> events(TStream<JsonObject> stream, Function<JsonObject, String> eventId, UnaryOperator<JsonObject> payload, Function<JsonObject, Integer> qos) { Function<JsonObject, String> topic = jo -> eventTopic(eventId.apply(jo)); Function<JsonObject,byte[]> payloadFn = jo -> JsonFunctions.asBytes().apply(payload.apply(jo)); return connector.publish(stream, topic, payloadFn, qos, jo -> retainEvents); }
@Test public void testMultiConnector() throws Exception { Topology top = newTopology("testMultiConnector"); MsgGenerator mgen = new MsgGenerator(top.getName()); int qos = 0; boolean retain = false; String pubClientId = newClientId(top.getName())+"_pub"; String subClientId = newClientId(top.getName())+"_sub"; String topic = getMqttTopics()[0]; List<String> msgs = createMsgs(mgen, topic, getMsg1(), getMsg2()); TStream<String> s = PlumbingStreams.blockingOneShotDelay( top.collection(msgs), PUB_DELAY_MSEC, TimeUnit.MILLISECONDS); // Test separate connectors for pub and sub MqttConfig config = newConfig(getServerURI(), pubClientId); MqttStreams mqttPub = new MqttStreams(top, () -> config); mqttPub.publish(s, topic, qos, retain); MqttConfig configSub = newConfig(getServerURI(), subClientId); MqttStreams mqttSub = new MqttStreams(top, () -> configSub); TStream<String> rcvd = mqttSub.subscribe(topic, qos); completeAndValidate(pubClientId, top, rcvd, mgen, SEC_TIMEOUT, msgs.toArray(new String[0])); }
@Test public void testQoS1() throws Exception { Topology top = newTopology("testQoS1"); MsgGenerator mgen = new MsgGenerator(top.getName()); int qos = 1; boolean retain = false; String clientId = newClientId(top.getName()); String topic = getMqttTopics()[0]; List<String> msgs = createMsgs(mgen, topic, getMsg1(), getMsg2()); TStream<String> s = PlumbingStreams.blockingOneShotDelay( top.collection(msgs), PUB_DELAY_MSEC, TimeUnit.MILLISECONDS); // TODO something to verify that we actually provide // the QoS semantics. // Test publish(TStream<String>, topic, qos) // Test TStream<String> subscribe(topic, qos) MqttConfig config = newConfig(getServerURI(), clientId); MqttStreams mqtt = new MqttStreams(top, () -> config); mqtt.publish(s, topic, qos, retain); TStream<String> rcvd = mqtt.subscribe(topic, qos); completeAndValidate(clientId, top, rcvd, mgen, SEC_TIMEOUT, msgs.toArray(new String[0])); }
MqttStreams mqtt = new MqttStreams(top, () -> config); mqtt.publish(s, topic, qos, retain); TStream<String> rcvd = mqtt.subscribe(topic, qos, new BiFunction<String, byte[], String>() { private static final long serialVersionUID = 1L;
@Test public void testMultipleServerURL() throws Exception { Topology top = newTopology("testMultipleServerURL"); MsgGenerator mgen = new MsgGenerator(top.getName()); int qos = 0; boolean retain = false; String clientId = newClientId(top.getName()); String topic = getMqttTopics()[0]; List<String> msgs = createMsgs(mgen, topic, getMsg1(), getMsg2()); TStream<String> s = PlumbingStreams.blockingOneShotDelay( top.collection(msgs), PUB_DELAY_MSEC, TimeUnit.MILLISECONDS); // Test server URL selection - supply a bogus 1st URL. String[] serverURLs = new String[] {"tcp://localhost:31999", getServerURI()}; MqttConfig config = newConfig(serverURLs[0], clientId); config.setServerURLs(serverURLs); MqttStreams mqtt = new MqttStreams(top, () -> config); mqtt.publish(s, topic, qos, retain); TStream<String> rcvd = mqtt.subscribe(topic, qos); completeAndValidate(clientId, top, rcvd, mgen, SEC_TIMEOUT, msgs.toArray(new String[0])); }
@Test public void testMultiTopicSubscribe() throws Exception { Topology top = newTopology("testMultiTopicSubscribe"); MsgGenerator mgen = new MsgGenerator(top.getName()); int qos = 0; boolean retain = false; String clientId = newClientId(top.getName()); String topic1 = getMqttTopics()[0] + "/1"; String topic2 = getMqttTopics()[0] + "/2"; String topics = getMqttTopics()[0] + "/+"; List<String> msgs1 = createMsgs(mgen, topic1, getMsg1(), getMsg2()); List<String> msgs2 = createMsgs(mgen, topic2, getMsg1(), getMsg2()); List<String> msgs = new ArrayList<>(); msgs.addAll(msgs1); msgs.addAll(msgs2); TStream<String> s1 = PlumbingStreams.blockingOneShotDelay( top.collection(msgs1), PUB_DELAY_MSEC, TimeUnit.MILLISECONDS); TStream<String> s2 = PlumbingStreams.blockingOneShotDelay( top.collection(msgs2), PUB_DELAY_MSEC, TimeUnit.MILLISECONDS); // Test multi-topic subscribe MqttConfig config = newConfig(getServerURI(), clientId); MqttStreams mqtt = new MqttStreams(top, () -> config); mqtt.publish(s1, topic1, qos, retain); mqtt.publish(s2, topic2, qos, retain); TStream<String> rcvd = mqtt.subscribe(topics, qos); completeAndValidate(false/*ordered*/, clientId, top, rcvd, mgen, SEC_TIMEOUT, msgs.toArray(new String[0])); }
@Test public void testStringPublish() throws Exception { Topology top = newTopology("testStringPublish"); MsgGenerator mgen = new MsgGenerator(top.getName()); int qos = 0; boolean retain = false; String clientId = newClientId(top.getName()); String topic = getMqttTopics()[0]; List<String> msgs = createMsgs(mgen, topic, getMsg1(), getMsg2()); TStream<String> s = PlumbingStreams.blockingOneShotDelay( top.collection(msgs), PUB_DELAY_MSEC, TimeUnit.MILLISECONDS); // Test publish(TStream<String>, topic, qos) // Test TStream<String> subscribe(topic, qos) MqttConfig config = newConfig(getServerURI(), clientId); MqttStreams mqtt = new MqttStreams(top, () -> config); TSink<String> sink = mqtt.publish(s, topic, qos, retain); TStream<String> rcvd = mqtt.subscribe(topic, qos); completeAndValidate(clientId, top, rcvd, mgen, SEC_TIMEOUT, msgs.toArray(new String[0])); assertNotNull(sink); }
@Test public void testActionTime() throws Exception { Topology top = newTopology("testActionTime"); MsgGenerator mgen = new MsgGenerator(top.getName()); int qos = 0; boolean retain = false; String clientId = newClientId(top.getName()); String topic = getMqttTopics()[0]; List<String> msgs = createMsgs(mgen, topic, getMsg1(), getMsg2()); TStream<String> s = PlumbingStreams.blockingOneShotDelay( top.collection(msgs), PUB_DELAY_MSEC, TimeUnit.MILLISECONDS); // Test publish(TStream<String>, topic, qos) // Test TStream<String> subscribe(topic, qos) MqttConfig config = newConfig(getServerURI(), clientId); config.setActionTimeToWaitMillis(3*1000); MqttStreams mqtt = new MqttStreams(top, () -> config); mqtt.publish(s, topic, qos, retain); TStream<String> rcvd = mqtt.subscribe(topic, qos); completeAndValidate(clientId, top, rcvd, mgen, SEC_TIMEOUT, msgs.toArray(new String[0])); }
@Test public void testSslClientAuth() throws Exception { Topology top = newTopology("testSslClientAuth"); MsgGenerator mgen = new MsgGenerator(top.getName()); int qos = 0; boolean retain = false; String clientId = newClientId(top.getName()); String topic = getMqttTopics()[0]; List<String> msgs = createMsgs(mgen, topic, getMsg1(), getMsg2()); TStream<String> s = PlumbingStreams.blockingOneShotDelay( top.collection(msgs), PUB_DELAY_MSEC, TimeUnit.MILLISECONDS); // Test publish(TStream<String>, topic, qos) // Test TStream<String> subscribe(topic, qos) // System.setProperty("javax.net.debug", "ssl"); // or "all"; "help" for full list setSslAuthInfo("sslClientAuth"); MqttConfig config = newConfig(getSslClientAuthServerURI(), clientId); MqttStreams mqtt = new MqttStreams(top, () -> config); TSink<String> sink = mqtt.publish(s, topic, qos, retain); TStream<String> rcvd = mqtt.subscribe(topic, qos); completeAndValidate(clientId, top, rcvd, mgen, SEC_TIMEOUT, msgs.toArray(new String[0])); assertNotNull(sink); }
@Test public void testSsl() throws Exception { Topology top = newTopology("testSsl"); MsgGenerator mgen = new MsgGenerator(top.getName()); int qos = 0; boolean retain = false; String clientId = newClientId(top.getName()); String topic = getMqttTopics()[0]; List<String> msgs = createMsgs(mgen, topic, getMsg1(), getMsg2()); TStream<String> s = PlumbingStreams.blockingOneShotDelay( top.collection(msgs), PUB_DELAY_MSEC, TimeUnit.MILLISECONDS); // Test publish(TStream<String>, topic, qos) // Test TStream<String> subscribe(topic, qos) // System.setProperty("javax.net.debug", "ssl"); // or "all"; "help" for full list setSslAuthInfo("ssl"); MqttConfig config = newConfig(getSslServerURI(), clientId); MqttStreams mqtt = new MqttStreams(top, () -> config); TSink<String> sink = mqtt.publish(s, topic, qos, retain); TStream<String> rcvd = mqtt.subscribe(topic, qos); completeAndValidate(clientId, top, rcvd, mgen, SEC_TIMEOUT, msgs.toArray(new String[0])); assertNotNull(sink); }
@Test public void testQoS2() throws Exception { Topology top = newTopology("testQoS2"); MsgGenerator mgen = new MsgGenerator(top.getName()); int qos = 2; boolean retain = false; String clientId = newClientId(top.getName()); String topic = getMqttTopics()[0]; List<String> msgs = createMsgs(mgen, topic, getMsg1(), getMsg2()); TStream<String> s = PlumbingStreams.blockingOneShotDelay( top.collection(msgs), PUB_DELAY_MSEC, TimeUnit.MILLISECONDS); // TODO something to verify that we actually provide // the QoS semantics. // Also improve code coverage with persistence override // Test publish(TStream<String>, topic, qos) // Test TStream<String> subscribe(topic, qos) MqttConfig config = newConfig(getServerURI(), clientId); config.setPersistence(new MemoryPersistence()); MqttStreams mqtt = new MqttStreams(top, () -> config); mqtt.publish(s, topic, qos, retain); TStream<String> rcvd = mqtt.subscribe(topic, qos); completeAndValidate(clientId, top, rcvd, mgen, SEC_TIMEOUT, msgs.toArray(new String[0])); }