PageRenderTime 45ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/org.eclipse.paho.sample.mqttv3app/src/main/java/org/eclipse/paho/sample/mqttv3app/SampleAsyncWait.java

https://github.com/Jacyzon/paho.mqtt.java
Java | 425 lines | 231 code | 42 blank | 152 comment | 28 complexity | 6a20e0e31c120ece378606735d6b5675 MD5 | raw file
  1. /*******************************************************************************
  2. * Copyright (c) 2009, 2014 IBM Corp.
  3. *
  4. * All rights reserved. This program and the accompanying materials
  5. * are made available under the terms of the Eclipse Public License v1.0
  6. * and Eclipse Distribution License v1.0 which accompany this distribution.
  7. *
  8. * The Eclipse Public License is available at
  9. * http://www.eclipse.org/legal/epl-v10.html
  10. * and the Eclipse Distribution License is available at
  11. * http://www.eclipse.org/org/documents/edl-v10.php.
  12. *
  13. * Contributors:
  14. * Dave Locke - initial API and implementation and/or initial documentation
  15. */
  16. package org.eclipse.paho.sample.mqttv3app;
  17. import java.io.IOException;
  18. import java.sql.Timestamp;
  19. import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
  20. import org.eclipse.paho.client.mqttv3.IMqttToken;
  21. import org.eclipse.paho.client.mqttv3.MqttAsyncClient;
  22. import org.eclipse.paho.client.mqttv3.MqttCallback;
  23. import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
  24. import org.eclipse.paho.client.mqttv3.MqttException;
  25. import org.eclipse.paho.client.mqttv3.MqttMessage;
  26. import org.eclipse.paho.client.mqttv3.persist.MqttDefaultFilePersistence;
  27. /**
  28. * A sample application that demonstrates how to use the Paho MQTT v3.1 Client API in
  29. * non-blocking waiter mode.
  30. *
  31. * It can be run from the command line in one of two modes:
  32. * - as a publisher, sending a single message to a topic on the server
  33. * - as a subscriber, listening for messages from the server
  34. *
  35. * There are three versions of the sample that implement the same features
  36. * but do so using using different programming styles:
  37. * <ol>
  38. * <li>Sample which uses the API which blocks until the operation completes</li>
  39. * <li>SampleAsyncWait (this one) shows how to use the asynchronous API with waiters that block until
  40. * an action completes</li>
  41. * <li>SampleAsyncCallBack shows how to use the asynchronous API where events are
  42. * used to notify the application when an action completes<li>
  43. * </ol>
  44. *
  45. * If the application is run with the -h parameter then info is displayed that
  46. * describes all of the options / parameters.
  47. */
  48. public class SampleAsyncWait implements MqttCallback {
  49. /**
  50. * The main entry point of the sample.
  51. *
  52. * This method handles parsing the arguments specified on the
  53. * command-line before performing the specified action.
  54. */
  55. public static void main(String[] args) {
  56. // Default settings:
  57. boolean quietMode = false;
  58. String action = "publish";
  59. String topic = "";
  60. String message = "Message from async waiter Paho MQTTv3 Java client sample";
  61. int qos = 2;
  62. String broker = "m2m.eclipse.org";
  63. int port = 1883;
  64. String clientId = null;
  65. String subTopic = "Sample/#";
  66. String pubTopic = "Sample/Java/v3";
  67. boolean cleanSession = true; // Non durable subscriptions
  68. boolean ssl = false;
  69. String userName = null;
  70. String password = null;
  71. // Parse the arguments -
  72. for (int i=0; i<args.length; i++) {
  73. // Check this is a valid argument
  74. if (args[i].length() == 2 && args[i].startsWith("-")) {
  75. char arg = args[i].charAt(1);
  76. // Handle arguments that take no-value
  77. switch(arg) {
  78. case 'h': case '?': printHelp(); return;
  79. case 'q': quietMode = true; continue;
  80. }
  81. // Now handle the arguments that take a value and
  82. // ensure one is specified
  83. if (i == args.length -1 || args[i+1].charAt(0) == '-') {
  84. System.out.println("Missing value for argument: "+args[i]);
  85. printHelp();
  86. return;
  87. }
  88. switch(arg) {
  89. case 'a': action = args[++i]; break;
  90. case 't': topic = args[++i]; break;
  91. case 'm': message = args[++i]; break;
  92. case 's': qos = Integer.parseInt(args[++i]); break;
  93. case 'b': broker = args[++i]; break;
  94. case 'p': port = Integer.parseInt(args[++i]); break;
  95. case 'i': clientId = args[++i]; break;
  96. case 'c': cleanSession = Boolean.valueOf(args[++i]).booleanValue(); break;
  97. case 'k': System.getProperties().put("javax.net.ssl.keyStore", args[++i]); break;
  98. case 'w': System.getProperties().put("javax.net.ssl.keyStorePassword", args[++i]); break;
  99. case 'r': System.getProperties().put("javax.net.ssl.trustStore", args[++i]); break;
  100. case 'v': ssl = Boolean.valueOf(args[++i]).booleanValue(); break;
  101. case 'u': userName = args[++i]; break;
  102. case 'z': password = args[++i]; break;
  103. default:
  104. System.out.println("Unrecognised argument: "+args[i]);
  105. printHelp();
  106. return;
  107. }
  108. } else {
  109. System.out.println("Unrecognised argument: "+args[i]);
  110. printHelp();
  111. return;
  112. }
  113. }
  114. // Validate the provided arguments
  115. if (!action.equals("publish") && !action.equals("subscribe")) {
  116. System.out.println("Invalid action: "+action);
  117. printHelp();
  118. return;
  119. }
  120. if (qos < 0 || qos > 2) {
  121. System.out.println("Invalid QoS: "+qos);
  122. printHelp();
  123. return;
  124. }
  125. if (topic.equals("")) {
  126. // Set the default topic according to the specified action
  127. if (action.equals("publish")) {
  128. topic = pubTopic;
  129. } else {
  130. topic = subTopic;
  131. }
  132. }
  133. String protocol = "tcp://";
  134. if (ssl) {
  135. protocol = "ssl://";
  136. }
  137. String url = protocol + broker + ":" + port;
  138. if (clientId == null || clientId.equals("")) {
  139. clientId = "SampleJavaV3_"+action;
  140. }
  141. // With a valid set of arguments, the real work of
  142. // driving the client API can begin
  143. try {
  144. // Create an instance of this class
  145. SampleAsyncWait sampleClient = new SampleAsyncWait(url,clientId,cleanSession, quietMode,userName,password);
  146. // Perform the specified action
  147. if (action.equals("publish")) {
  148. sampleClient.publish(topic,qos,message.getBytes());
  149. } else if (action.equals("subscribe")) {
  150. sampleClient.subscribe(topic,qos);
  151. }
  152. } catch(MqttException me) {
  153. // Display full details of any exception that occurs
  154. System.out.println("reason "+me.getReasonCode());
  155. System.out.println("msg "+me.getMessage());
  156. System.out.println("loc "+me.getLocalizedMessage());
  157. System.out.println("cause "+me.getCause());
  158. System.out.println("excep "+me);
  159. me.printStackTrace();
  160. }
  161. }
  162. // Private instance variables
  163. private MqttAsyncClient client;
  164. private String brokerUrl;
  165. private boolean quietMode;
  166. private MqttConnectOptions conOpt;
  167. private boolean clean;
  168. private String password;
  169. private String userName;
  170. /**
  171. * Constructs an instance of the sample client wrapper
  172. * @param brokerUrl the url to connect to
  173. * @param clientId the client id to connect with
  174. * @param cleanSession clear state at end of connection or not (durable or non-durable subscriptions)
  175. * @param quietMode whether debug should be printed to standard out
  176. * @param userName the username to connect with
  177. * @param password the password for the user
  178. * @throws MqttException
  179. */
  180. public SampleAsyncWait(String brokerUrl, String clientId, boolean cleanSession,
  181. boolean quietMode, String userName, String password) throws MqttException {
  182. this.brokerUrl = brokerUrl;
  183. this.quietMode = quietMode;
  184. this.clean = cleanSession;
  185. this.userName = userName;
  186. this.password = password;
  187. //This sample stores in a temporary directory... where messages temporarily
  188. // stored until the message has been delivered to the server.
  189. //..a real application ought to store them somewhere
  190. // where they are not likely to get deleted or tampered with
  191. String tmpDir = System.getProperty("java.io.tmpdir");
  192. MqttDefaultFilePersistence dataStore = new MqttDefaultFilePersistence(tmpDir);
  193. try {
  194. // Construct the connection options object that contains connection parameters
  195. // such as cleanSession and LWT
  196. conOpt = new MqttConnectOptions();
  197. conOpt.setCleanSession(clean);
  198. if(password != null ) {
  199. conOpt.setPassword(this.password.toCharArray());
  200. }
  201. if(userName != null) {
  202. conOpt.setUserName(this.userName);
  203. }
  204. // Construct a non-blocking MQTT client instance
  205. client = new MqttAsyncClient(this.brokerUrl,clientId, dataStore);
  206. // Set this wrapper as the callback handler
  207. client.setCallback(this);
  208. } catch (MqttException e) {
  209. e.printStackTrace();
  210. log("Unable to set up client: "+e.toString());
  211. System.exit(1);
  212. }
  213. }
  214. /**
  215. * Publish / send a message to an MQTT server
  216. * @param topicName the name of the topic to publish to
  217. * @param qos the quality of service to delivery the message at (0,1,2)
  218. * @param payload the set of bytes to send to the MQTT server
  219. * @throws MqttException
  220. */
  221. public void publish(String topicName, int qos, byte[] payload) throws MqttException {
  222. // Connect to the MQTT server
  223. // issue a non-blocking connect and then use the token to wait until the
  224. // connect completes. An exception is thrown if connect fails.
  225. log("Connecting to "+brokerUrl + " with client ID "+client.getClientId());
  226. IMqttToken conToken = client.connect(conOpt,null,null);
  227. conToken.waitForCompletion();
  228. log("Connected");
  229. String time = new Timestamp(System.currentTimeMillis()).toString();
  230. log("Publishing at: "+time+ " to topic \""+topicName+"\" qos "+qos);
  231. // Construct the message to send
  232. MqttMessage message = new MqttMessage(payload);
  233. message.setQos(qos);
  234. // Send the message to the server, control is returned as soon
  235. // as the MQTT client has accepted to deliver the message.
  236. // Use the delivery token to wait until the message has been
  237. // delivered
  238. IMqttDeliveryToken pubToken = client.publish(topicName, message, null, null);
  239. pubToken.waitForCompletion();
  240. log("Published");
  241. // Disconnect the client
  242. // Issue the disconnect and then use a token to wait until
  243. // the disconnect completes.
  244. log("Disconnecting");
  245. IMqttToken discToken = client.disconnect(null, null);
  246. discToken.waitForCompletion();
  247. log("Disconnected");
  248. }
  249. /**
  250. * Subscribe to a topic on an MQTT server
  251. * Once subscribed this method waits for the messages to arrive from the server
  252. * that match the subscription. It continues listening for messages until the enter key is
  253. * pressed.
  254. * @param topicName to subscribe to (can be wild carded)
  255. * @param qos the maximum quality of service to receive messages at for this subscription
  256. * @throws MqttException
  257. */
  258. public void subscribe(String topicName, int qos) throws MqttException {
  259. // Connect to the MQTT server
  260. // issue a non-blocking connect and then use the token to wait until the
  261. // connect completes. An exception is thrown if connect fails.
  262. log("Connecting to "+brokerUrl + " with client ID "+client.getClientId());
  263. IMqttToken conToken = client.connect(conOpt,null, null);
  264. conToken.waitForCompletion();
  265. log("Connected");
  266. // Subscribe to the requested topic.
  267. // Control is returned as soon client has accepted to deliver the subscription.
  268. // Use a token to wait until the subscription is in place.
  269. log("Subscribing to topic \""+topicName+"\" qos "+qos);
  270. IMqttToken subToken = client.subscribe(topicName, qos, null, null);
  271. subToken.waitForCompletion();
  272. log("Subscribed to topic \""+topicName);
  273. // Continue waiting for messages until the Enter is pressed
  274. log("Press <Enter> to exit");
  275. try {
  276. System.in.read();
  277. } catch (IOException e) {
  278. //If we can't read we'll just exit
  279. }
  280. // Disconnect the client
  281. // Issue the disconnect and then use the token to wait until
  282. // the disconnect completes.
  283. log("Disconnecting");
  284. IMqttToken discToken = client.disconnect(null, null);
  285. discToken.waitForCompletion();
  286. log("Disconnected");
  287. }
  288. /**
  289. * Utility method to handle logging. If 'quietMode' is set, this method does nothing
  290. * @param message the message to log
  291. */
  292. private void log(String message) {
  293. if (!quietMode) {
  294. System.out.println(message);
  295. }
  296. }
  297. /****************************************************************/
  298. /* Methods to implement the MqttCallback interface */
  299. /****************************************************************/
  300. /**
  301. * @see MqttCallback#connectionLost(Throwable)
  302. */
  303. public void connectionLost(Throwable cause) {
  304. // Called when the connection to the server has been lost.
  305. // An application may choose to implement reconnection
  306. // logic at this point. This sample simply exits.
  307. log("Connection to " + brokerUrl + " lost!" + cause);
  308. System.exit(1);
  309. }
  310. /**
  311. * @see MqttCallback#deliveryComplete(IMqttDeliveryToken)
  312. */
  313. public void deliveryComplete(IMqttDeliveryToken token) {
  314. // Called when a message has been delivered to the
  315. // server. The token passed in here is the same one
  316. // that was passed to or returned from the original call to publish.
  317. // This allows applications to perform asynchronous
  318. // delivery without blocking until delivery completes.
  319. //
  320. // This sample demonstrates asynchronous deliver and
  321. // uses the token.waitForCompletion() call in the main thread which
  322. // blocks until the delivery has completed.
  323. // Additionally the deliveryComplete method will be called if
  324. // the callback is set on the client
  325. //
  326. // If the connection to the server breaks before delivery has completed
  327. // delivery of a message will complete after the client has re-connected.
  328. // The getPendinTokens method will provide tokens for any messages
  329. // that are still to be delivered.
  330. try {
  331. log("Delivery complete callback: Publish Completed "+token.getMessage());
  332. } catch (Exception ex) {
  333. log("Exception in delivery complete callback"+ex);
  334. }
  335. }
  336. /**
  337. * @see MqttCallback#messageArrived(String, MqttMessage)
  338. */
  339. public void messageArrived(String topic, MqttMessage message) throws MqttException {
  340. // Called when a message arrives from the server that matches any
  341. // subscription made by the client
  342. String time = new Timestamp(System.currentTimeMillis()).toString();
  343. System.out.println("Time:\t" +time +
  344. " Topic:\t" + topic +
  345. " Message:\t" + new String(message.getPayload()) +
  346. " QoS:\t" + message.getQos());
  347. }
  348. /****************************************************************/
  349. /* End of MqttCallback methods */
  350. /****************************************************************/
  351. static void printHelp() {
  352. System.out.println(
  353. "Syntax:\n\n" +
  354. " SampleAsyncWait [-h] [-a publish|subscribe] [-t <topic>] [-m <message text>]\n" +
  355. " [-s 0|1|2] -b <hostname|IP address>] [-p <brokerport>] [-i <clientID>]\n\n" +
  356. " -h Print this help text and quit\n" +
  357. " -q Quiet mode (default is false)\n" +
  358. " -a Perform the relevant action (default is publish)\n" +
  359. " -t Publish/subscribe to <topic> instead of the default\n" +
  360. " (publish: \"Sample/Java/v3\", subscribe: \"Sample/#\")\n" +
  361. " -m Use <message text> instead of the default\n" +
  362. " (\"Message from MQTTv3 Java client\")\n" +
  363. " -s Use this QoS instead of the default (2)\n" +
  364. " -b Use this name/IP address instead of the default (m2m.eclipse.org)\n" +
  365. " -p Use this port instead of the default (1883)\n\n" +
  366. " -i Use this client ID instead of SampleJavaV3_<action>\n" +
  367. " -c Connect to the server with a clean session (default is false)\n" +
  368. " \n\n Security Options \n" +
  369. " -u Username \n" +
  370. " -z Password \n" +
  371. " \n\n SSL Options \n" +
  372. " -v SSL enabled; true - (default is false) " +
  373. " -k Use this JKS format key store to verify the client\n" +
  374. " -w Passpharse to verify certificates in the keys store\n" +
  375. " -r Use this JKS format keystore to verify the server\n" +
  376. " If javax.net.ssl properties have been set only the -v flag needs to be set\n" +
  377. "Delimit strings containing spaces with \"\"\n\n" +
  378. "Publishers transmit a single message then disconnect from the server.\n" +
  379. "Subscribers remain connected to the server and receive appropriate\n" +
  380. "messages until <enter> is pressed.\n\n"
  381. );
  382. }
  383. }